package com.luxsoft.sw3.cfd;

import java.awt.Dimension;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.SwingUtilities;

import mx.gob.sat.cfd.x2.ComprobanteDocument;
import mx.gob.sat.cfd.x2.ComprobanteDocument.Comprobante;
import mx.gob.sat.cfd.x2.ComprobanteDocument.Comprobante.Emisor;
import mx.gob.sat.cfd.x2.ComprobanteDocument.Comprobante.Conceptos.Concepto;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperPrintManager;
import net.sf.jasperreports.engine.data.JRTableModelDataSource;
import net.sf.jasperreports.view.JRViewer;

import org.apache.commons.lang.StringUtils;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.orm.hibernate3.HibernateCallback;

import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.gui.TableFormat;
import ca.odell.glazedlists.swing.EventTableModel;

import com.jgoodies.uif.util.ScreenUtils;
import com.luxsoft.siipap.cxc.model.NotaDeCargo;
import com.luxsoft.siipap.cxc.model.NotaDeCredito;
import com.luxsoft.siipap.cxc.model.NotaDeCreditoBonificacion;
import com.luxsoft.siipap.cxc.model.NotaDeCreditoDevolucion;
import com.luxsoft.siipap.cxc.model.OrigenDeOperacion;
import com.luxsoft.siipap.cxc.old.ImporteALetra;
import com.luxsoft.siipap.model.core.Cliente;
import com.luxsoft.siipap.service.ServiceLocator2;
import com.luxsoft.siipap.swing.reports.ReportUtils;
import com.luxsoft.siipap.swing.utils.MessageUtils;
import com.luxsoft.siipap.swing.utils.SWExtUIManager;
import com.luxsoft.siipap.util.DateUtil;
import com.luxsoft.siipap.util.MonedasUtils;
import com.luxsoft.siipap.ventas.model.Devolucion;
import com.luxsoft.siipap.ventas.model.Venta;
import com.luxsoft.siipap.ventas.model.VentaDet;
import com.luxsoft.sw3.cfd.model.ComprobanteFiscal;
import com.luxsoft.sw3.impap.services.CFDPrintServices;

public class CFDPrintServicesCxC
{

    public CFDPrintServicesCxC()
    {
    }

    public static void imprimirNotaDeCreditoDevolucion(NotaDeCreditoDevolucion nota, ComprobanteFiscal cf, String destinatario, boolean printPreview)
    {
        cf.loadComprobante();
        String cadenaOriginal = getCadenaOriginal(cf.getComprobanteDocument());
        Map parametros = CFDParametrosUtils.resolverParametros(nota, cf, cadenaOriginal);
        parametros.put("DESTINATARIO", destinatario);
        net.sf.jasperreports.engine.JasperPrint jasperPrint = null;
        DefaultResourceLoader loader = new DefaultResourceLoader();
        String reportDir = System.getProperty("cfd.report.dir", "");
        String reportName = "NotaDevDigital.jasper";
        Resource res = loader.getResource((new StringBuilder(String.valueOf(reportDir))).append(reportName).toString());
        try
        {
            java.io.InputStream io = res.getInputStream();
            net.sf.jasperreports.engine.data.JRTableModelDataSource tmDataSource = CFDTableModelUtils.getTableModel(nota);
            jasperPrint = JasperFillManager.fillReport(io, parametros, tmDataSource);
            if(printPreview)
            {
                JRViewer jasperViewer = new JRViewer(jasperPrint);
                jasperViewer.setPreferredSize(new Dimension(900, 1000));
                ReportDialog dialog = new ReportDialog(jasperViewer, "Comprobante digital", false);
                ScreenUtils.locateOnScreenCenter(dialog);
                dialog.open();
            } else
            {
                JasperPrintManager.printReport(jasperPrint, false);
            }
        }
        catch(Exception ioe)
        {
            ioe.printStackTrace();
            MessageUtils.showError("Error imprimiendo CFD", ioe);
            return;
        }
    }

    public static void impripirComprobante(Venta venta, ComprobanteFiscal cf, String destinatario, boolean printPreview)
    {
        CFDPrintServices.impripirComprobante(venta, cf, destinatario, printPreview);
    }

    public static ComprobanteFiscal buscarComprobante(String origenId)
    {
        String hql = "from ComprobanteFiscal c where c.origen=?";
        return (ComprobanteFiscal)ServiceLocator2.getHibernateTemplate().find(hql, origenId).iterator().next();
    }

    public static String getCadenaOriginal(ComprobanteDocument document)
    {
        return ServiceLocator2.getCFDManager().generarCadenaOriginal(document);
    }
    
    
public static void imprimirNotaDeCargoElectronica(String notaDeCargoId){
		
		NotaDeCargo nota=buscarNotaInicializada(notaDeCargoId);
		if(nota==null)
			return;
		ComprobanteFiscal cf=buscarComprobante(nota.getId());
		cf.loadComprobante();
		List<Concepto> conceptosArray=Arrays.asList(cf.getComprobante().getConceptos().getConceptoArray());
		final EventList<Concepto> conceptos=GlazedLists.eventList(conceptosArray);
		Map parametros=resolverParametros(nota,null);
		
		JasperPrint jasperPrint = null;
		DefaultResourceLoader loader = new DefaultResourceLoader();
		Resource res = loader.getResource(ReportUtils
				.toReportesPath("cxc/NotaCarDigitalImpap.jasper"));
		System.out.println("Generando impresion de CFD con parametros: "+parametros);
		try {
			java.io.InputStream io = res.getInputStream();
			String[] columnas= {"cantidad","descripcion","valorUnitario","importe","descripcion"};
			String[] etiquetas={"CANTIDAD","DESCRIPCION","PRECIO","IMPORTE","GRUPO"};
			final TableFormat tf=GlazedLists.tableFormat(columnas, etiquetas);
			
			final EventTableModel tableModel=new EventTableModel(conceptos,tf);
			final JRTableModelDataSource tmDataSource=new JRTableModelDataSource(tableModel);
			jasperPrint = JasperFillManager.fillReport(io, parametros,tmDataSource);
			
			JRViewer jasperViewer = new JRViewer(jasperPrint);
			jasperViewer.setPreferredSize(new Dimension(900, 1000));
			ReportDialog dialog=new ReportDialog(jasperViewer,"Nota de cargo digital",false);
			ScreenUtils.locateOnScreenCenter(dialog);
			dialog.open();
			
		} catch (Exception ioe) {
			ioe.printStackTrace();
			MessageUtils.showError("Error imprimiendo CFD", ioe);
			return;
		}		
	}

private static NotaDeCargo buscarNotaInicializada(final String id){
	
	return (NotaDeCargo)ServiceLocator2.getHibernateTemplate().execute(new HibernateCallback(){

		public Object doInHibernate(Session session) throws HibernateException, SQLException {
			NotaDeCargo res=(NotaDeCargo)session.get(NotaDeCargo.class, id);
			res.getCliente().getTelefonosRow();
			if(!res.getAplicaciones().isEmpty()){
				res.getAplicaciones().iterator().next();
			}
			return res;
		}
		
	});
	
}

public static Map resolverParametros(NotaDeCargo nota,ComprobanteFiscal cf){
	if(cf==null)
		cf=buscarComprobante(nota.getId());
	cf.loadComprobante();
	Comprobante comprobante=cf.getComprobante();
	Map<String, Object> parametros = new HashMap<String, Object>();
	
	// Datos tomados del Comprobante fiscal digital XML
	
	parametros.put("FOLIO", 			comprobante.getSerie()+"-"+comprobante.getFolio());
	parametros.put("ANO_APROBACION", 	comprobante.getAnoAprobacion());
	parametros.put("NO_APROBACION", 	comprobante.getNoAprobacion().intValue());
	parametros.put("NUM_CERTIFICADO", 	comprobante.getNoCertificado()); //Recibir como Parametro
	parametros.put("SELLO_DIGITAL", 	comprobante.getSello()); //Recibir como Parametro
	parametros.put("CADENA_ORIGINAL", 	getCadenaOriginal(cf.getComprobanteDocument())); //Recibir como Parametro
	parametros.put("NOMBRE", 			comprobante.getReceptor().getNombre()); //Recibir como Parametro
	parametros.put("RFC", 				comprobante.getReceptor().getRfc());
	parametros.put("FECHA", 			comprobante.getFecha().getTime());
	parametros.put("NFISCAL", 			comprobante.getSerie()+" - "+comprobante.getFolio());		
	parametros.put("IMPORTE", 			comprobante.getSubTotal()); 
	parametros.put("IMPUESTO", 			comprobante.getImpuestos().getTotalImpuestosTrasladados()); 
	parametros.put("TOTAL", 			comprobante.getTotal()); 
	parametros.put("DIRECCION", 		CFDUtils.getDireccionEnFormatoEstandar(comprobante.getReceptor().getDomicilio()));
	
	Emisor emisor=comprobante.getEmisor();
	parametros.put("EMISOR_NOMBRE", 	emisor.getNombre());
	parametros.put("EMISOR_RFC", 		emisor.getRfc());
	String pattern="{0} {1}  {2}" +
			"\n{3}" +
			"\n{4}" +
			"\n{5}  {6}";
	String direccionEmisor=MessageFormat.format(pattern
			,emisor.getDomicilioFiscal().getCalle()
			,emisor.getDomicilioFiscal().getNoExterior()
			,StringUtils.defaultIfEmpty(emisor.getDomicilioFiscal().getNoInterior(),"")
			
			,emisor.getDomicilioFiscal().getColonia()
			
			,emisor.getDomicilioFiscal().getMunicipio()
			
			,emisor.getDomicilioFiscal().getCodigoPostal()
			,emisor.getDomicilioFiscal().getEstado()
			);
	parametros.put("EMISOR_DIRECCION", direccionEmisor);
	
	//Datos tomado de la aplicacion
	
	parametros.put("CARGO_ID", 			nota.getId());
	parametros.put("IMP_CON_LETRA", 	ImporteALetra.aLetra(nota.getTotalCM()));
	parametros.put("SUCURSAL", 			nota.getSucursal().getId()); 		
	parametros.put("CLAVCTE", 			nota.getClave()); 		
	parametros.put("SUC", 				nota.getSucursal().getClave()); 
	
	parametros.put("TEL", 				nota.getCliente().getTelefonosRow());		
	parametros.put("D_REV", 			nota.getDiaRevision());
	parametros.put("D_PAG", 			nota.getDiaDelPago());
	parametros.put("COB", 				nota.getCobrador()!=null?nota.getCobrador().getId():null);
	
	parametros.put("PLAZO", 			nota.getPlazo());
	parametros.put("FREV", 				nota.isRevision()?"R":"");
	 
	parametros.put("TIPO", 				nota.getOrigen().toString());
	parametros.put("DOCTO", 			nota.getDocumento());		
	parametros.put("TAR_COM_IMP", 		nota.getCargos());
	parametros.put("COMENTARIO", 		nota.getComentario());
	parametros.put("COMENTARIO_CAR", 		nota.getComentario());
	
	
	parametros.put("ELAB_FAC", 		nota.getLog().getCreateUser());
	parametros.put("PINT_IVA",		MonedasUtils.IVA.multiply(BigDecimal.valueOf(100)));
	
	return parametros;
}
    

    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable() {

            public void run()
            {
                SWExtUIManager.setup();
                NotaDeCredito nota = (NotaDeCredito)ServiceLocator2.getCXCManager().getAbono("8a8a8197-2c3666da-012c-3736912a-0020");
                ComprobanteFiscal cf = CFDPrintServicesCxC.buscarComprobante(nota.getId());
                CFDPrintServicesCxC.imprimirNotaDeCreditoDevolucion((NotaDeCreditoDevolucion)nota, cf, null, true);
                System.exit(0);
            }

        }
);
    }
}


